﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using TipTepCore;
using TipTep.ImageAnalyzer;
using System.IO;
using System.Drawing;

namespace TipTep.Recorder
{
    internal class Recorder
    {
        private TipTepOpenNI.Frame depth;
        private TipTepCore.Point3D point3D;
        private System.Drawing.RectangleF handRectangle;
        private TipTepCore.Skeleton3D skeleton;

        /// <summary>
        /// CTOR
        /// </summary>
        /// <param name="depth">Depth image 640x480</param>
        /// <param name="point3D">Hand point in depth image</param>
        /// <param name="handRectangle">Hand surrounding rectangle</param>
        /// <param name="skeleton">Hand skeleton in depth image</param>
        public Recorder(TipTepOpenNI.Frame depth, TipTepCore.Point3D point3D, System.Drawing.RectangleF handRectangle, TipTepCore.Skeleton3D skeleton)
        {
            // TODO: Complete member initialization
            this.depth = depth;
            this.point3D = point3D;
            this.handRectangle = handRectangle;
            this.skeleton = skeleton;
        }

        /// <summary>
        /// Record hand data to XML file
        /// * Depth image of the hand
        /// * Hand point
        /// * Hand rectangle
        /// * Hand skeleton
        /// </summary>
        internal void RecordHandData()
        {
            XmlDocument xmlToRecord = new XmlDocument();
            xmlToRecord.AppendChild(xmlToRecord.CreateXmlDeclaration("1.0", "utf-8", "yes"));
            xmlToRecord.AppendChild(xmlToRecord.CreateNode(XmlNodeType.Element, "HandData", ""));

            XmlElement depthImageWithbackgroundXml = xmlToRecord.CreateElement("HandDepthImageWithBackground");
            XmlElement depthImageWithoutBackgroundXml = xmlToRecord.CreateElement("HandDepthImageWithBackground");
            DepthImage depthImage = new DepthImage(640, 408, 10000, depth.GetData());
            ImageAnalyzer.HandImageExtractor handExtractor = new ImageAnalyzer.HandImageExtractor(depthImage, point3D, 10000);
            DepthImage handImageWithBackground = handExtractor.GetHandImageRegion();
            DepthImage handImageWithoutBackground = handExtractor.GetExtractedHandImage();

            if (handImageWithoutBackground == null)
            {
                return;
            }

            for (int k = 0; k < handImageWithBackground.ImageData.Count; k++)
            {
                XmlElement pixel = xmlToRecord.CreateElement("Pixel_" + k.ToString());
                pixel.SetAttribute("Data", Convert.ToString(handImageWithBackground.ImageData[k]));
                depthImageWithbackgroundXml.AppendChild(pixel);
            }

            for (int k = 0; k < handImageWithoutBackground.ImageData.Count; k++)
            {
                XmlElement pixel = xmlToRecord.CreateElement("Pixel_" + k.ToString());
                pixel.SetAttribute("Data", Convert.ToString(handImageWithoutBackground.ImageData[k]));
                depthImageWithoutBackgroundXml.AppendChild(pixel);
            }

            #region Hand Point

            XmlElement handPointXml = xmlToRecord.CreateElement("HandPoint");
            if (point3D != null)
            {
                handPointXml.SetAttribute("X", Convert.ToString(point3D.X));
                handPointXml.SetAttribute("Y", Convert.ToString(point3D.Y));
                handPointXml.SetAttribute("Z", Convert.ToString(point3D.Z));
            }

            #endregion

            #region Hand Rectangle

            XmlElement handRectangleXml = xmlToRecord.CreateElement("Handrectangle");
            if(handRectangle != null)
            {
                handRectangleXml.SetAttribute("X", Convert.ToString(handRectangle.X));
                handRectangleXml.SetAttribute("Y", Convert.ToString(handRectangle.Y));
                handRectangleXml.SetAttribute("Width", Convert.ToString(handRectangle.Width));
                handRectangleXml.SetAttribute("Height", Convert.ToString(handRectangle.Height));
            }

            #endregion

            #region Skeleton

            XmlElement skeletonXml = xmlToRecord.CreateElement("Skeleton");
            if (skeleton != null && skeleton.Lines != null)
            {
                foreach (Line3D line in skeleton.Lines)
                {
                    XmlElement lineXml = xmlToRecord.CreateElement("Line");
                    lineXml.SetAttribute("StartX", line.Start.X.ToString());
                    lineXml.SetAttribute("StartY", line.Start.Y.ToString());
                    lineXml.SetAttribute("StartZ", line.Start.Z.ToString());
                    
                    lineXml.SetAttribute("EndX", line.End.X.ToString());
                    lineXml.SetAttribute("EndY", line.End.Y.ToString());
                    lineXml.SetAttribute("EndZ", line.End.Z.ToString());
                    
                    skeletonXml.AppendChild(lineXml);
                }
            }

            #endregion
            
            xmlToRecord.DocumentElement.AppendChild(handPointXml);
            xmlToRecord.DocumentElement.AppendChild(handRectangleXml);
            xmlToRecord.DocumentElement.AppendChild(skeletonXml);
            xmlToRecord.DocumentElement.AppendChild(depthImageWithoutBackgroundXml);
            xmlToRecord.DocumentElement.AppendChild(depthImageWithbackgroundXml);

            DirectoryInfo dir = Directory.CreateDirectory(Properties.Settings.Default.Location + DateTime.Now.Date.ToString("yyyy-M-dd") + "\\" + DateTime.Now.Ticks);
            xmlToRecord.Save(dir.FullName + "\\HandData.xml");
            Bitmap img = handImageWithBackground.Get2DImage(ImageTransferMode2D.OpenNIHistogram);
            img.Save(dir.FullName + "\\HandImageWithBackground.bmp");
            img = handImageWithoutBackground.Get2DImage(ImageTransferMode2D.Monochrome);
            img.Save(dir.FullName + "\\HandImageWithoutBackground.bmp");

        }
    }
}
